function animate1(el) {
    var frameCount = 0;
    var timer = setInterval(function () {
      el.style.left = parseFloat(window.getComputedStyle(el).left) + 20 + "px";
      frameCount++;
  
      /* 停止动画定时器 */
      if (frameCount === 25) {
        clearInterval(timer);
      }
    }, 40);
  }
  
  /**
   * 动画轮子
   * @param {HTMLElement} el 要动画的元素
   * @param {Object} targetObj 动画目标位置
   * @param {number} duration 动画完成时长
   */
  function animate2(el, targetObj, duration = 1000) {
    // 计算总帧数
    var totalFrames = (25 * duration) / 1000;
  
    // 动态记录动画运行了多少帧 总帧数一到就停止动画
    var frameCount = 0;
  
    /* 
      计划让targetObj同时存储每个属性的目标值+动画速度
      {
          left:["300px",speed],
          top:["400px",speed]
      },
    */
  
    /* 计算动画速度 */
    // 一次性拿到动画前的所有属性值
    var currentStyles = window.getComputedStyle(el);
    console.log("currentStyles", currentStyles);
  
    /* 计算所有属性的动画速度 */
    for (var key in targetObj) {
      var targetValue = targetObj[key];
  
      // 属性的动画速度 = (目标值-当前值)/动画帧数
      var speed =
        (parseFloat(targetValue) - parseFloat(currentStyles[key])) / totalFrames;
  
      // { left:["300px",speed], }
      // 重构targetObj
      targetObj[key] = [targetValue, speed];
    }
    console.log("targetObj", targetObj);
  
    var timer = setInterval(function () {
      // el.style.left = parseFloat(window.getComputedStyle(el).left) + 20 + "px";
  
      /* 每一帧 每个属性 都要在上一帧的基础上偏移一个动画速度 */
      for (var key in targetObj) {
        // 让left在上一帧的基础上偏移一个动画速度
        // { left:["300px",speed], }
        el.style[key] =
          parseFloat(window.getComputedStyle(el)[key]) + targetObj[key][1] + "px";
      }
  
      // 更新帧数
      frameCount++;
  
      /* 总帧数到达目标时 停止动画定时器 */
      if (frameCount === totalFrames) {
        clearInterval(timer);
  
        //暴力将元素校正到目标位置
        for (var key in targetObj) {
          el.style[key] = targetObj[key][0];
        }
      }
    }, 40);
  }
  
  /**
   * 从形如"300px"中分离值与单位 得到形如[300,"px"]的结果
   * @param {string} str
   * @returns {any[]}
   */
  function getUnit(str) {
    str += ""
    var num = parseFloat(str)
    var unit = str.slice((num+"").length)
    return [num,unit]
  }
  
  /**
   * 动画轮子
   * @param {HTMLElement} el 要动画的元素
   * @param {Object} targetObj 动画目标位置
   * @param {number} duration 动画完成时长
   */
  function animate3(el, targetObj, duration = 1000) {
    // 计算总帧数
    var totalFrames = (25 * duration) / 1000;
  
    // 动态记录动画运行了多少帧 总帧数一到就停止动画
    var frameCount = 0;
  
    /* 
      计划让targetObj同时存储每个属性的目标值+动画速度
      {
          left:[300,"px",speed],
          opacity:[0.5,"",speed]
      },
    */
  
    /* 计算动画速度 */
    // 一次性拿到动画前的所有属性值
    var currentStyles = window.getComputedStyle(el);
    console.log("currentStyles", currentStyles);
  
    /* 计算所有属性的动画速度 */
    for (var key in targetObj) {
      // 300px
      var targetValue = targetObj[key];
      var numUnitArr = getUnit(targetValue);
  
      // [300,"px"]
      var num = numUnitArr[0];
      var unit = numUnitArr[1];
  
      // 属性的动画速度 = (目标值-当前值)/动画帧数
      var speed = (num - parseFloat(currentStyles[key])) / totalFrames;
  
      // { left:["300px",speed], }
      // 重构targetObj
      // targetObj[key] = [targetValue, speed];
      targetObj[key] = [num, unit, speed];
    }
    console.log("targetObj", targetObj);
  
    var timer = setInterval(function () {
      // el.style.left = parseFloat(window.getComputedStyle(el).left) + 20 + "px";
  
      /* 每一帧 每个属性 都要在上一帧的基础上偏移一个动画速度 */
      for (var key in targetObj) {
        // 让left在上一帧的基础上偏移一个动画速度
        // { left:[300,"px",speed], }
        el.style[key] =
          parseFloat(window.getComputedStyle(el)[key]) +
          targetObj[key][2] +
          targetObj[key][1];
      }
  
      // 更新帧数
      frameCount++;
  
      /* 总帧数到达目标时 停止动画定时器 */
      if (frameCount === totalFrames) {
        clearInterval(timer);
  
        //暴力将元素校正到目标位置
        for (var key in targetObj) {
          el.style[key] = targetObj[key][0];
        }
      }
    }, 40);
  }
  
  /**
   * 动画轮子
   * @param {HTMLElement} el 要动画的元素
   * @param {Object} targetObj 动画目标位置
   * @param {number} duration 动画完成时长
   * @param {function} callback 动画结束回调函数
   */
  function animate4(el, targetObj, duration = 1000, callback = null) {
    // 计算总帧数
    var totalFrames = 25 * (duration / 1000);
  
    // 动态记录动画运行了多少帧 总帧数一到就停止动画
    var frameCount = 0;
  
    /* 
      计划让targetObj同时存储每个属性的目标值+动画速度
      {
          left:[300,"px",speed],
          opacity:[0.5,"",speed]
      },
    */
  
    /* 计算动画速度 */
    // 一次性拿到动画前的所有属性值
    var currentStyles = window.getComputedStyle(el);
  
    /* 计算所有属性的动画速度 */
    // { left:[300,"px",speed], }
    for (var key in targetObj) {
      var targetValue = targetObj[key]; // 300px
      let [num, unit] = getUnit(targetValue); // [300,"px"]
      // var num = numUnitArr[0]
      // var unit = numUnitArr[1]
  
      // 属性的动画速度 = (目标值-当前值)/动画帧数
      var speed = (num - parseFloat(currentStyles[key])) / totalFrames;
  
      // 重构targetObj { left:["300px",speed], }
      targetObj[key] = [num, unit, speed];
    }
  
    /* 动画定时器 每40毫秒动一下（折合一秒25帧） */
    var timer = setInterval(function () {
      /* 每一帧 每个属性 都要在上一帧的基础上偏移一个动画速度 */
      for (var key in targetObj) {
        var arr = targetObj[key]; //[300 "px" speed]
  
        // var num=arr[0],unit=arr[1],speed=arr[2]
        let [num, unit, speed] = arr;
  
        el.style[key] = parseFloat(window.getComputedStyle(el)[key]) + speed + unit
      }
  
      // 更新帧数
      frameCount++;
  
      /* 总帧数到达目标时 停止动画定时器 */
      if (frameCount === totalFrames) {
        // 动画结束
        clearInterval(timer);
  
        //暴力将元素校正到目标位置
        // arr形如 [300 "px" speed]
        for (var arr in targetObj) {
          // 将arr中的3个元素依次提取出来 命名为num,unit,speed
          // var num=arr[0],unit=arr[1],speed=arr[2]
          let [num, unit, speed] = arr;
  
          //暴力将元素校正到目标位置
          el.style[key] = num + unit;
        }
  
        /* 如果有回调函数则回调之 */
        callback && callback();
      }
    }, 40);
  }
  
  /* 动画轮子 共计代码29行 */
  function animate(el,targetObj,duration=1000,callback=null){
    var totalFrames = 25*(duration/1000)
    var frameCount = 0
    var currentStyles = window.getComputedStyle(el)
  
    for(var key in targetObj){
      var arr = getUnit(targetObj[key])
      var num = arr[0]
      var unit = arr[1]
      var speed = (num - parseFloat(currentStyles[key]))/totalFrames
      targetObj[key] = [num,unit,speed]
    }
  
    var timer = setInterval(
      function(){
        for(var key in targetObj){
          var arr = targetObj[key]
          el.style[key] = parseFloat(window.getComputedStyle(el)[key])+arr[2]+arr[1]
        }
  
        frameCount++
  
        if(frameCount===totalFrames){
          clearInterval(timer)
          for(var key in targetObj){
            el.style[key] = targetObj[key]
          }
          callback && callback()
        }
      },
      40
    )
  }






[box1, box2, box3].forEach(function (item) {
    item.onclick = function () {
      animate(
        item,
        {
          left: "300px",
          top: "400px",
          opacity: 0.5,
        },
        1000,

        // 动画结束时的回调函数
        function () {
          console.log("动画结束惹");
        }
      );
    };
  });


